package exam.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import exam.bean.SysMenuInfo;
import exam.bean.UserGroup;
import exam.bean.UserInfo;
import exam.common.dto.SysMenuDto;
import exam.dao.GroupAndMenuInfoDao;
import exam.service.IGroupAndMenuInfoService;
import exam.service.IUserInfoService;
import exam.service.UserGroupService;
import exam.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class GroupAndMenuInfoServiceImpl implements IGroupAndMenuInfoService {

    @Autowired
    GroupAndMenuInfoDao groupAndMenuInfoDao;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    IUserInfoService userInfoService;

    @Autowired
    UserGroupService userGroupService;

    @Override
    public String getPermissionMenu(UserInfo userInfo) {

        String permStr = "";

//        System.out.println("权限列表转字符串函数");

        try{
            if (redisUtil.hasKey("GrantedAuthority:" + userInfo.getName())) {
                permStr = (String) redisUtil.get("GrantedAuthority:" + userInfo.getName());
//                System.out.println("权限列表有缓存"+permStr);
            }else{
                //获取权限组id
                Integer permissionGroupId = groupAndMenuInfoDao.getPermissionGroupId(userInfo.getUserGroupId());

                //依据关联表获取所有权限id
                List<Integer> permissionIds = groupAndMenuInfoDao.getPermissionId(permissionGroupId);

                //依据关联表中数据获取所有满足的权限值
                List<String> permStrings = groupAndMenuInfoDao.getAuthorizationInfo(permissionIds);

                //将所有用户权限拼接成字符串（以逗号分割）
                if(permStrings.size() >0){
                    permStr = String.join(",", permStrings);
                }
                //拼接角色（用户组）
                permStr = "ROSE_".concat(userInfo.getUserGroupName()).concat(",").concat(permStr);

                //将权限进行缓存
                redisUtil.set("GrantedAuthority:" + userInfo.getName(), permStr,60 * 60);
//            System.out.println("权限列表没有缓存"+permStr);
            }
        }catch (Exception e){
            System.out.println(e.getMessage());
        }

        return permStr;
    }

    /**
     * 根据用户名删除权限缓存
     * @param username  用户名
     */
    @Override
    public void clearUserAuthorityInfo(String username) {
        redisUtil.del("GrantedAuthority:"+username);
    }

    /**
     * 根据用户组id清空用户权限缓存
     * @param groupId  用户组id
     */
    @Override
    public void clearUserAuthorityInfoByGroupId(Integer groupId) {
        //根据用户组id获取用户信息
        Map<String,Object> queryMap = new HashMap<>();
        queryMap.put("userGroupId",groupId);
        System.out.println(queryMap);
        clearUserAuthorityInfo(userInfoService.selectInfoSingle(queryMap).getName());
    }

    /**
     * 根据权限组id清空用户权限缓存
     * @param permissionGroupId  权限组id
     */
    @Override
    public void clearUserAuthorityInfoByMenuId(Integer permissionGroupId) {
        //根据权限组id获取用户组id
        Map<String,Object> queryMap = new HashMap<>();
        queryMap.put("permissionGroupId",permissionGroupId);
        clearUserAuthorityInfoByGroupId(userGroupService.selectInfoSingle(queryMap).getId());
    }

    /**
     * 删除当前登录用户权限缓存
     */
    @Override
    public void clearCurrentUserAuthorityInfo(){
       String username = null;
       if(!StrUtil.isBlankOrUndefined(username)){
           clearUserAuthorityInfo(username);
       }
    }

    @Override
    public List<SysMenuDto> getMenuList() {
//        System.out.println("————————————————获取用户导航栏——————————————————————");
        //获取当前用户名称
        String userName = (String)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Map<String,Object> queryMap = new HashMap<>();
        queryMap.put("name",userName);
        UserInfo userInfo = userInfoService.selectInfoSingle(queryMap);

//        System.out.println("当前用户信息："+userInfo.getName());

        //获取当前用户菜单栏（权限）id
        List<Integer>  menuIds = groupAndMenuInfoDao
                .getPermissionId(groupAndMenuInfoDao
                        .getPermissionGroupId(userInfo.getUserGroupId()));

//        System.out.println("当前用户菜单栏"+ JSONUtil.toJsonStr(menuIds));

        //根据菜单栏（权限id）获取菜单栏信息
        List<SysMenuInfo> sysMenuInfos = groupAndMenuInfoDao.getMenuInfoById(menuIds);

//        System.out.println("当前菜单栏信息"+JSONUtil.toJsonStr(sysMenuInfos));

        //转树状结构
        List<SysMenuInfo> menuTree = buildTree(sysMenuInfos);

//        System.out.println("树状结构："+JSONUtil.toJsonStr(menuTree));
         //转dto
//        System.out.println("————————————————获取结束——————————————————————");
        return convert(menuTree);
    }

    private List<SysMenuDto> convert(List<SysMenuInfo> menuTree) {
        List<SysMenuDto> menuDtos = new ArrayList<>();
        menuTree.forEach(m -> {
            SysMenuDto dto = new SysMenuDto();
            dto.setId(m.getId());
            dto.setName(m.getPerms());
            dto.setTitle(m.getName());
            dto.setComponent(m.getComponent());
            dto.setPath(m.getPath());
            if (m.getChildren().size() > 0) {
                // 子节点调用当前方法进行再次转换
                dto.setChildren(convert(m.getChildren()));
            }
            menuDtos.add(dto);
        });
        return menuDtos;
    }

    private List<SysMenuInfo> buildTree(List<SysMenuInfo> sysMenuInfos) {
        List<SysMenuInfo> finalMenu = new ArrayList<>();

//        System.out.println("进入转换函数"+JSONUtil.toJsonStr(sysMenuInfos));

        // 先各自寻找到各自的孩子
        for (SysMenuInfo menu : sysMenuInfos) {
            for (SysMenuInfo e : sysMenuInfos) {
                if (menu.getId() == e.getParent_id()) {
                    menu.getChildren().add(e);
                }
            }
            // 提取出父节点
            if (menu.getParent_id() == 0) {
                finalMenu.add(menu);
            }
        }

//        System.out.println(JSONUtil.toJsonStr(finalMenu));

        return finalMenu;
    }

    @Override
    public List<Integer> getMenuIdByGroupId(Integer groupId) {
        Integer permGroupId = groupAndMenuInfoDao.getPermissionGroupId(groupId);
        return groupAndMenuInfoDao.getPermissionId(permGroupId);
    }

    @Override
    public List<SysMenuDto> allPermissionMenuInfo() {
        List<SysMenuInfo> sysMenuInfos =  groupAndMenuInfoDao.allPermissionMenuInfo();
        return convert(buildTree(sysMenuInfos));
    }
}
